-module(socket_sup).
-behaviour(supervisor).

-define(SERVER, ?MODULE).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
-define(CHILD_SUP(I), {I, {I, start_link, []}, permanent, infinity, supervisor, [I]}).

-export([start_link/0]).
-export([init/1]).

start_link() ->
    supervisor:start_link({local, ?SERVER}, ?MODULE, []).

init([]) ->
    Childs = [
        ?CHILD_SUP(ranch_sup),
        ranch_listen_sup()
    ],
    {ok, {{one_for_one, 10, 10}, Childs}}.

ranch_listen_sup() ->
    NodeOpts        = cfg:get(ou:get_node_sname(node()), []),
    TOpts           = proplists:get_value(t_opts, NodeOpts, []),
    % Ref             = socket_listener_mgr,
    NumAcceptors    = proplists:get_value(acceptors, TOpts, 10),
    % Transport       = ranch_tcp,
    TransOpts       = proplists:get_value(socket_opts, TOpts, [{ip, {0, 0, 0, 0}}, {port, 5555}]) ++ [{keepalive, true}, {max_connections, 10240 * NumAcceptors}],
    % ProtocolSup     = socket_protocol_sup,
    ProtoOpts       = make_protocol_opts(TOpts),
    ranch:child_spec(socket_protocol, NumAcceptors, ranch_tcp, TransOpts, socket_protocol, ProtoOpts).

make_protocol_opts(TOpts) ->
    ProtoMap = #{  
        encoder => pb_codec,
        decoder => pb_codec,
        handler => msg_handler
    },
    case proplists:get_value(proto_opts, TOpts, []) of
        [] -> ProtoMap;
        Opts ->
            ProtoMap1 = maps:from_list(Opts),
            case maps:is_key(encoder, ProtoMap1) andalso maps:is_key(decoder, ProtoMap1) andalso maps:is_key(handler, ProtoMap1) of
                true -> ProtoMap1;
                false -> ProtoMap
            end
    end.
